package lapsnake.model.dnd;

import java.awt.Point;

import javax.swing.JPanel;

import lapsnake.model.LapNode;
import lapsnake.model.data.ChildField;

public class Socket
{
	JPanel locPanel;
	private ChildField<?> parentField;
	private int fieldIndex;
	private boolean horizontal;
	private Point offset;
	private StmtPanel rootPanel;
	
	/**
	 * 
	 * @param locPanel The UI panel that this socket is relative to. Note that this is only used to compute the absolute location.
	 * This field may be null. Then the offset is taken to be the location relative to the root dragging ui panel.
	 * @param parentField The ChildField corresponding to this socket on the parent node.<br> 
	 * If a NodePanel for LapNode A is dropped into this socket, and this socket 
	 * corresponds to ChildField F on LapNode B, then A will be inserted into field F.  
	 * @param fieldIndex The index in the parentField where new nodes will be added. 
	 * For single-element ChildFields this should always be 0.
	 * @param horizontal Whether this is a horizontal-oriented socket. This has two implications:
	 * <li>The socket is on a horizontal part of the border of the panel and is visually horizontally oriented, e.g. the 16x8 icon is used. 
	 * New nodes snap on <i>under</i> the socket.</li>
	 * <li>A horizontal socket implies that a node can be <i>added</i> to or <i>inserted</i> into the field, 
	 * while a vertical socket means that the field's value can be <i>replaced</i>.</li>
	 * Vertical sockets should only be used where there is already a value. Horizontal sockets should only be used where there is room for another value.
	 * @param offset The offset of this socket's origin from the parentPanel's origin.
	 */
	public<T extends LapNode> Socket(StmtPanel rootPanel, JPanel locPanel, ChildField<T> parentField, int fieldIndex, boolean horizontal, Point offset)
	{
		super();
		this.rootPanel = rootPanel;
		this.locPanel = locPanel;
		this.parentField = parentField;
		this.horizontal = horizontal;
		this.offset = offset;
	}

	public Point getAbsoluteLocation()
	{
		Point p;
		if (locPanel == null)
			p = new Point();
		else
		{
			p = locPanel.getLocationOnScreen();
			Point origin = rootPanel.getLocationOnScreen();
			p.x -= origin.x;
			p.y -= origin.y;
		}
		p.x += offset.x;
		p.y += offset.y;
		return p;
	}
	@Override
	public String toString()
	{
		return "Socket "+parentField+"["+fieldIndex+"] "+(horizontal?'h':'v')+" "+offset+" relative to "+locPanel;
	}

	public boolean accepts(LapNode node)
	{
		return parentField.getType().isAssignableFrom(node.getClass());
	}
}
	
